package com.minelx.statementsplus;

import com.minelx.landisk.filesystem.core.File;
import com.minelx.sqlstructures.statements.SelectBuilder;
import com.minelx.sqlstructures.statements.clause.*;

import java.io.*;
import java.util.function.Function;

// FIXME 2021/7/14  wait for me!!!     remove Serializable
public class ChildSqlBuilder implements IChildSqlBuilder {
	private static final String ID = "{{ID}}";

	private static final String IDS = "{{IDS}}";

	private final String parentKey;

	private final SelectBuilder selectBuilder;

	private ChildSqlBuilder(String parentKey, SelectBuilder selectBuilder) {
		this.parentKey = parentKey;
		this.selectBuilder = selectBuilder;
		this.selectBuilder.select().add(Field.of(parentKey));
		this.selectBuilder.where().add(Conditions.in(ID, IDS).toText());
	}

	@Override
	public ChildSqlBuilder addField(Field added) {
		selectBuilder.select().add(added);
		return this;
	}

	public ChildSqlBuilder where(Sql condition) {
		selectBuilder.where().add(condition.toText());
		return this;
	}

	@Override
	public Sql asSql() {
		return () -> header() + selectBuilder.build().toText();
	}

	public SelectBuilder body() {
		return selectBuilder;
	}

	@Override
	public String parentKey() {
		return parentKey;
	}

	private String header() {
		return "2=>(" + parentKey + ") ";
	}

	@Override
	public String toString() {
		return "ChildSqlBuilder{" +
				"parentKey='" + parentKey + '\'' +
				", tableName=" + selectBuilder.select().getTableName() +
				", fields=" + selectBuilder.select().getFields() +
				'}';
	}

	public static ChildSqlBuilder create(String parentKey, SelectBuilder selectBuilder) {
		return new ChildSqlBuilder(parentKey, selectBuilder);
	}

	public static ChildSqlBuilder create(String parentKey, String tableName) {
		return create(
				parentKey,
				new SelectBuilder(new SelectClauseBuilder(tableName), AndBuilder.empty(), Sql.empty(), Sql.empty())
		);
	}

	// FIXME 2021/7/17  wait for me!!!     remove itm
	public void save(OutputStream out) {
		try (ObjectOutputStream destination = new ObjectOutputStream(out)) {
			destination.writeObject(this);
		} catch (IOException e) {
			throw new RuntimeException("something is wrong here", e);
		}
	}

	public static ChildSqlBuilder read(File file) {
		try (InputStream inputStream = file.inputStream()) {
			ObjectInputStream source = new ObjectInputStream(inputStream);
			return (ChildSqlBuilder) source.readObject();
		} catch (IOException | ClassNotFoundException e) {
			throw new RuntimeException("something is wrong here", e);
		}
	}
}
